请先登录

拆开 Multica 的源码,看看 Agent 看板到底怎么跑的

883 字

极客工具 2026年6月14日 09:56

图片

上篇写了 Multica 的产品体验,自托管部署后跑了几个真实 Issue。体验下来感觉不错——Agent 在评论区主动汇报进度,Issue 状态自动流转,比 tmux 分屏加复制粘贴 prompt 好太多。

但体验好是一回事,适不适合长期用是另一回事。我现在的 AI 助手栈是 OpenClaw,日常记忆、生活管理、多渠道通信都在上面跑。要引入 Multica,得先搞清楚它底层到底怎么跑的、能不能跟 OpenClaw 并行、对接成本高不高。

于是花了两天读源码。结论:Multica 的核心价值不在发明新 Agent 能力,而在 一个干净的协作调度层 。它把 13 种 CLI 统一到一个接口下,用 Issue 做任务追溯,用 Daemon 做本地执行。设计很克制,工程水平很高。

一句话定位

Multica 不是 Agent 框架,不是 AI 模型,是一个 协作管理层 ——管的是 谁做什么、做到哪了、结果是什么

类比一下:Kubernetes 管容器调度,Multica 管 Agent 调度。你不关心里面跑的是什么镜像,你关心的是 调度策略

三层架构

Multica 由三层组成,物理分离:

部署位置 职责
用户交互层 用户设备 Web UI / Desktop / iOS / CLI
服务端层 Cloud 或自托管 REST API + WebSocket,任务调度
执行层 开发者本机 Daemon 调用 Agent CLI

关键设计: 服务端不知道 Agent 怎么执行 。它只负责调度和状态管理。实际执行完全由 Daemon 在本地完成。这种分离让 Multica 可以支持任意 CLI,不需要服务端了解每个 Agent 的 API。

图片)

三层架构:服务端不知道 Agent 怎么执行,只管调度和状态管理。实际执行完全由 Daemon 在本地完成。

最有价值的代码:Agent Backend 抽象

server/pkg/agent/agent.go 里定义了一个统一接口:

type Backend interface {
    Execute(ctx context.Context, prompt string, opts ExecOptions) (*Session, error)
}

每个 CLI 一个实现文件,13 个 Backend 横向展开:

13 个 Backend 横向展开,每个 CLI 一个文件: claude.go / codex.go / copilot.go / openclaw.go / opencode.go / cursor.go / gemini.go / hermes.go / kimi.go / kiro.go / pi.go / antigravity.go / codebuddy.go

每个 Backend 实现同样的 Execute 方法,但内部处理各自的 CLI 调用差异。比如:

  • claude.go 处理 Session 恢复和 thinking level
  • codex.go 处理 sandbox 策略和 multi-agent
  • openclaw.go 有 local/gateway 模式切换
  • cursor.go 处理 Unix/Windows 调用差异

新增一个 CLI 只需加一个文件,实现接口,完事。这就是 插件化 的正确姿势。

Daemon 怎么跑任务

Daemon 是运行在开发者本机的后台进程,五个步骤循环执行:

  1. 1. 检测 :扫描 PATH 上的 claude/codex/copilot 等 CLI
  2. 2. 注册 :设备名、可用 CLI、版本上报到服务端
  3. 3. 轮询 :每 3s 向服务端 claim 任务
  4. 4. 执行 :调用对应 CLI 处理 Issue
  5. 5. 上报 :WebSocket 流式推送执行进度

任务执行的生命周期

图片)

Issue 从创建到完成:入队 → 认领 → 执行 → 收尾,三层 watchdog 防止任务卡死。

几个工程细节值得注意:

EmptyClaimCache — 当某 runtime 没有待处理任务时缓存这个状态,Daemon 轮询时跳过 DB 查询。一个小优化,但在多 workspace 场景下大幅减少空查询。

双层 WatchdogIdleWatchdog 监控 Agent 总体空闲(30 分钟), ToolWatchdog 监控单个工具调用(2 小时)。分开设计是因为 Agent 可能整体在工作,但某个工具卡死了。

Orphan Recovery — Daemon 重启时主动上报:之前在跑的任务挂了,服务端立即标记失败并触发重试。不用等心跳超时(75s + 任务超时 2.5h)。

Prompt 不是直接丢给 Agent

Multica 不会把 Issue 描述直接丢给 CLI。它有 5 种结构化的 Prompt 构建器:

任务类型 构建器 场景
标准分配 BuildPrompt() multica issue get 理解任务
评论触发 buildCommentPrompt() 嵌入触发评论 + 回复指令
聊天 buildChatPrompt() 嵌入用户消息 + 附件列表
自动驾驶 buildAutopilotPrompt() 嵌入 Autopilot 指令
快速创建 buildQuickCreatePrompt() 结构化 Issue 创建

评论触发的 Prompt 特别精细:区分触发者是人类还是另一个 Agent。如果是 Agent-to-Agent,加入 沉默是金 规则避免 ping-pong 循环。

Squad 委派与防循环

Squad = 1 个领导 Agent + N 个成员(Agent 或人类)。分配给 Squad 的任务先到领导,领导有两条路:自己干,或者委派给某个成员 Agent。如果领导判断不需要行动,调用 multica squad activity no_action

防循环机制 :同一 Agent 在同一 Issue 上已有 pending task 时,新的 @提及被静默跳过。这条规则在 HasPendingTaskForIssueAndAgent 查询里实现,简单但有效。

@提及系统精确到 UUID,四种类型各有效果:

类型 格式 效果
agent [@Name](mention://agent/<uuid>) 触发该 Agent 执行
squad [@Name](mention://squad/<uuid>) 触发 Squad 领导
member [@Name](mention://member/<uuid>) 仅渲染链接,不触发
issue [@Name](mention://issue/<uuid>) 仅渲染链接
@all [@all](mention://all/all) 广播,抑制 assignee 自动触发

用 UUID 而不是名字,避免了重名问题。链接解析靠正则 mention://(member|agent|squad|issue|all)/([0-9a-fA-F-]+|all) ,名字混进去直接失效。

内置 Skill 系统:源码追踪

Multica 在服务端编译时嵌入了 7 个内置技能:

技能 用途
multica-autopilots 自动驾驶使用指南
multica-creating-agents 创建新 Agent
multica-mentioning @提及机制详解
multica-projects-and-resources 项目和资源管理
multica-runtimes-and-repos 运行时和仓库配置
multica-skill-importing 技能导入流程
multica-squads 小队委派机制
multica-working-on-issues Issue 工作流

这些技能是 source-traced contracts ——每个声明都标注了对应的 Go 源码位置。比如 multica-mentioning 技能里写了 util.MentionRe in server/internal/util/mention.go ,代码变了技能文档也要同步。还有一个 Go 行为测试 TestMentioningSkillTeachesTheParserContract 来验证技能文档和代码一致。

✏️ 这个思路很值得借鉴

技能文档和代码双向绑定。文档不是 写了就忘 的说明书,而是跟代码一起演化的活文档。

前端架构:严格的包边界

前端是 Monorepo,代码量 158K 行 TS/TSX(不含测试)。包结构三层分离:

  • packages/core/ — 无头业务逻辑(零 react-dom),包含 30+ 领域模块(api、issues、agents、squads 等)
  • packages/ui/ — 原子组件(零业务逻辑)
  • packages/views/ — 业务页面(零 next/* / react-router)

硬规则 :服务端数据只能用 TanStack Query 管理,WebSocket 事件只做 query invalidation, 禁止 直接写 store。客户端 UI 状态用 Zustand, 禁止 复制服务端数据到 Zustand。

还有一条 Parse, don't cast 规则——所有 API 响应通过 zod schema 解析 + fallback。因为 Electron 桌面端更新滞后于服务端,API 响应可能漂移。不加 fallback 就崩。这条规则来自 3 次真实事故。

实战体验:自托管部署

图片)

自托管后的首页。看板视图,Issue 卡片上有 Agent 头像。

图片)

Issue 详情页:Agent 被 @ 提及后自动执行,在评论区报告进度。注意右侧 进行中 状态和 紧急 优先级。

图片)

我的 Issue 视图。右上角运行时菜单有红点告警——实际部署时确实会碰到 Daemon 状态问题。

图片)

运行时管理页面。可以看到 Daemon 上线状态、可用 CLI 列表、版本号。

图片)

Issue 生命周期视图:todo → in_progress → done 的完整流转。

图片)

Autopilot 自动驾驶配置页面。可以设置 Cron 定时触发或 Webhook 触发。

跑了 3 个真实 Issue,Agent 在评论区主动汇报进度,完成后自动更新状态。整个流程比 tmux 分屏 + 手动复制 prompt 好太多。

我的选择:OpenClaw + Multica 双轨并行

读完源码后,我决定把 Multica 和 OpenClaw 并行使用,而不是替换。这是我个人实践中的选择,供参考。

图片)

Multica 做主控管调度,OpenClaw 作为 Backend 节点保留日常助手能力,Claude Code 做纯编码。两者共享同一个 Git 库和工作区。

为什么不直接换掉 OpenClaw

两个顾虑:

  1. 1. 运维惯性 — OpenClaw 已有自动化部署、更新脚本、配置推送。换一个工具意味着重建这套基建。
  2. 2. 生存风险 — Multica 没有大团队背书,开源项目随时可能停更。OpenClaw 社区活跃度高,一直在打补丁升级。

为什么要引入 Multica

OpenClaw 的结构性短板在于它是 对话驱动 而非 任务驱动

  • • Session 用随机 UUID 命名,无法自定义,找不到之前的对话
  • • 没有 任务 概念,只有 对话 ,中断了不知道进度到哪
  • • 不适合 提交一个有明确交付物的任务 这种工程场景

Multica 恰好补上这块:Issue 就是任务,有状态、有追溯、有结果。

分工方案

场景 用什么
工程任务、Issue 追踪、多 Agent 编码 Multica
日常记忆、生活管理、多渠道通信 OpenClaw
Claude Code 纯编码任务 Multica 直接调度
移动端随手记、微信通知 OpenClaw PWA

💡 对接成本很低

Multica 的 pkg/agent/openclaw.go 已有完整实现。 OpenclawMode 字段支持 local (本地内嵌)和 gateway (网关路由)两种模式。注册 OpenClaw 为 runtime,分配 Issue 给它执行就行。

当然这是我个人的方案,还在验证中。如果你也在用 OpenClaw 或者其他 Agent CLI,可以参考这个思路。

工程质量评价

注释质量极高

Go 代码的注释不是 这行做什么 ,而是 为什么这样做 。每个 const 有设计理由,每个 watchdog 引用了 issue 编号(MUL-XXXX),每个 bug fix 在注释中解释根因。这是成熟团队的标志。

事故驱动改进

事故 改进
#1661 UUID 解析三路分离(混合输入 / 纯 UUID / 可信传递)
#2143/2147/2192 API 响应防御性编程 + zod fallback
MUL-2300 IdleWatchdog 从 5min 调到 30min
MUL-3064 ToolWatchdog 独立于 IdleWatchdog

每次事故都有对应的代码改进和注释记录。不是 改了就忘 ,而是 改了就记下来 ,让后来的人理解为什么这么写。

代码规模

Go 125K 行 + TS 158K 行,不含测试。测试文件单独算的话再翻一倍。这个体量已经不是 玩具项目 了,是一个认真的工程。

局限性

Daemon 轮询有浪费

默认 3s 轮询,虽然有 EmptyClaimCache 优化,但在多 workspace 场景下仍然产生大量空请求。WebSocket push 模式会更好,但实现复杂度也更高。

内置技能硬编码

7 个内置技能编译时嵌入 Go 二进制,更新需要重新编译部署。虽然保证了版本一致性,但迭代不够灵活。

PostgreSQL 17 运维成本

自托管需要维护一个 PostgreSQL 17 + pgvector 实例。对小团队来说不是零成本。

没有预算控制

每个 Agent CLI 自己处理 API 账单,Multica 不在 UI 层展示 这个 Issue 花了多少钱 。需要精细成本控制的话,得去各自提供商后台查。

部署

自托管只需两步:

curl -fsSL https://raw.githubusercontent.com/multica-ai/multica/main/scripts/install.sh | bash -s -- --with-server
multica setup self-host

需要 Docker + Docker Compose。默认拉 GHCR 上的官方镜像。打开 http://localhost:3000 就能用。

总结

Multica 值得关注的原因不是它 功能多 ,而是它 设计干净

  • Backend 抽象层 统一 13 种 CLI,新增一个只需一个文件
  • Issue 做任务追溯 ,Agent 执行有状态、有记录、可恢复
  • Daemon 本地执行 ,代码不上传,隐私可控
  • Prompt 结构化构建 ,不是把需求直接丢给 Agent
  • 源码追踪技能 ,文档和代码双向绑定

对于已经在用多个 AI CLI 但苦于协作靠复制粘贴的团队,Multica 值得一试。

GitHub: multica-ai/multica [1] · Apache 2.0 · 36K+ Star

引用链接

[1] multica-ai/multica: https://github.com/multica-ai/multica

继续滑动看下一个

极客工具 XTool

向上滑动看下一个